#pragma once
namespace Wang
{
	template<class T>
	struct listNode
	{
		T _val;
		listNode* _next;
		listNode* _prev;
		listNode(const T& val)
			:_val(val), _next(this), _prev(this)
		{}
	};

	template<class T, class Ref, class Ptr>
	struct Iterator
	{
		typedef listNode<T> Node;
		Node* _pnode;
		Iterator(Node* ptr)
			:_pnode(ptr)
		{}

		Ref operator*()
		{
			return _pnode->_val;
		}

		Ptr operator->()
		{
			return &_pnode->_val;
		}

		Iterator& operator++()
		{
			_pnode = _pnode->_next;
			return *this;
		}

		Iterator& operator--()
		{
			_pnode = _pnode->_prev;
			return *this;
		}

		bool operator!=(const Iterator& it)
		{
			return _pnode != it._pnode;
		}
	};
	template<class T>
	class list
	{
		typedef listNode<T> Node;
	public:
		list() = default;

		list(const list& lt)
		{
			for (auto& e : lt)
				push_back(e);
		}

		list& operator=(list lt)
		{
			swap(lt._head, _head);
			swap(lt._size, _size);
			return *this;
		}

		void push_back(const T& val)
		{
			/*Node* cur = new Node(val);
			cur->_next = _head;
			cur->_prev = _head->_prev;
			_head->_prev->_next = cur;
			_head->_prev = cur;
			++_size;*/

			insert(end(), val);
		}

		void push_back(T&& val)
		{
			;
		}

		void pop_back()
		{
			Node* tail = _head->_prev;
			tail->_prev->_next = _head;
			_head->_prev = tail->_prev;
			delete tail;
			--_size;
		}

		typedef Iterator<T, T&, T*> iterator;
		typedef Iterator<T, const T&, const T*> const_iterator;
		iterator begin()
		{
			return _head->_next;
		}
		iterator end()
		{
			return _head;
		}
		const_iterator begin() const
		{
			return _head->_next;
		}
		const_iterator end() const
		{
			return _head;
		}
		bool empty() { return _size == 0; }
		iterator insert(iterator pos, const T& val)
		{
			Node* cur = new Node(val);
			cur->_next = pos._pnode;
			cur->_prev = pos._pnode->_prev;

			pos._pnode->_prev->_next = cur;
			pos._pnode->_prev = cur;
			++_size;
			return pos;
		}

		iterator erase(iterator pos)
		{
			if(pos != end())
			{
				Node* cur = pos._pnode;
				cur->_prev->_next = cur->_next;
				cur->_next->_prev = cur->_prev;
				delete cur;
				--_size;
				return ++pos;
			}
			return pos;
		}
	private:
		Node* _head = new Node(T());
		size_t _size = 0;
	};
}